package com.authsphere.security.configurer.password.configurers;

import com.authsphere.plugin.api.AuthSphereAfterPluginChain;
import com.authsphere.plugin.api.AuthSphereBeforePluginChain;
import com.authsphere.security.common.configurers.AbstractAuthSphereAuthenticationFilterConfigurer;
import com.authsphere.security.common.user.DefaultEnhanceUserDetailsService;
import com.authsphere.security.common.user.EnhanceUserDetailsService;
import com.authsphere.security.configurer.password.filter.UsernamePasswordRequestBodyAuthenticationFilter;
import com.authsphere.security.configurer.password.provider.UsernamePasswordAuthenticationProvider;
import com.authsphere.security.web.handler.AuthenticationHandler;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.ResolvableType;
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;

/**
 * @program: AuthSphere
 * @description:
 * @author: YuKai Fan
 * @create: 2025/3/11 17:02
 **/
public class UsernamePasswordAuthenticationFilterConfigurer<H extends HttpSecurityBuilder<H>> extends
        AbstractAuthSphereAuthenticationFilterConfigurer<H, UsernamePasswordAuthenticationFilterConfigurer<H>, UsernamePasswordRequestBodyAuthenticationFilter> {

    private String processingUrl;


    private AuthenticationHandler authenticationHandler;

    public UsernamePasswordAuthenticationFilterConfigurer() {
        super(UsernamePasswordAuthenticationFilter.class);
    }

    @Override
    protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) {
        return new AntPathRequestMatcher(loginProcessingUrl, "POST");
    }

    @Override
    public void init(H http) throws Exception {
        UsernamePasswordRequestBodyAuthenticationFilter authenticationFilter = new UsernamePasswordRequestBodyAuthenticationFilter();
        authenticationFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
        if (StringUtils.isNotBlank(processingUrl)) {
            authenticationFilter.setFilterProcessesUrl(processingUrl);
        }
        authenticationFilter.setAuthenticationHandler(getAuthenticationHandler(http));
        this.setAuthenticationFilter(authenticationFilter);
        UserDetailsService userDetailsService = getUserDetailsService();
        UsernamePasswordAuthenticationProvider usernamePasswordAuthenticationProvider = new UsernamePasswordAuthenticationProvider();
        usernamePasswordAuthenticationProvider.setUserDetailsService(userDetailsService);
        http.authenticationProvider(this.postProcess(usernamePasswordAuthenticationProvider));
    }

    private AuthenticationHandler getAuthenticationHandler(H http) {
        if (authenticationHandler != null) {
            return authenticationHandler;
        }
        return http.getSharedObject(AuthenticationHandler.class);
    }

    private EnhanceUserDetailsService getUserDetailsService() {
        ResolvableType type = ResolvableType.forType(EnhanceUserDetailsService.class);
        EnhanceUserDetailsService bean = getBeanOrNull(type);
        return (bean != null) ? bean : new DefaultEnhanceUserDetailsService();
    }

    public UsernamePasswordAuthenticationFilterConfigurer<H> processingUrl(String processingUrl) {
        this.processingUrl = processingUrl;
        return this;
    }

    public UsernamePasswordAuthenticationFilterConfigurer<H> setAuthenticationHandler(AuthenticationHandler authenticationHandler) {
        this.authenticationHandler = authenticationHandler;
        return this;
    }
}
